#include "balanca.h"
#include <sys/timeb.h>
#include <QThread>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

Balanca::Balanca(QObject *parent) :
    QObject(parent)
{
    m_serialPort.setParent(this);
}

QString Balanca::port() {
    return this->m_port;
}

void Balanca::setPort(QString port) {
    this->m_port = port;
}

QString Balanca::baudrate() {
    return this->m_baudrate;
}

void Balanca::setBaudrate(QString baudrate) {
    this->m_baudrate = baudrate;
}

int Balanca::timeoutInMillis() {
    return this->m_timeoutInMillis;
}

void Balanca::setTimeoutInMillis(int timeoutInMillis) {
    this->m_timeoutInMillis = timeoutInMillis;
}

float Balanca::readIntervalInSeconds() {
    return 0.001;
}

bool Balanca::abrir_conexao() {
    m_serialPort.setPortName(m_port);
    if(!m_serialPort.open(QIODevice::ReadWrite)) return false;

    m_serialPort.setBaudRate(getBaudFromString(m_baudrate));

    return true;
}

void Balanca::fechar_conexao() {
    m_serialPort.close();
}

bool Balanca::checar_peso(double peso) {
    QVariantMap dados_balanca = get_dados();

    return dados_balanca.contains(K_PESO) && (dados_balanca.value(K_PESO).toDouble() == peso);
}

qint32 Balanca::getBaudFromString(QString baud) {
    qint32 result;

    switch(baud.toInt()) {
    case 1200: result = QSerialPort::Baud1200; break;
    case 2400: result = QSerialPort::Baud2400; break;
    case 4800: result = QSerialPort::Baud4800; break;
    case 9600: result = QSerialPort::Baud9600; break;
    case 19200: result = QSerialPort::Baud19200; break;
    case 38400: result = QSerialPort::Baud38400; break;
    case 57600: result = QSerialPort::Baud57600; break;
    case 115200: result = QSerialPort::Baud115200; break;
    default: result = DEFAULT_BAUD;
    }

    return result;
}

int Balanca::readByte(char *byte) {
    m_serialPort.flush();
    if(!m_serialPort.waitForReadyRead(10)) {
        m_serialPort.flush();
        m_serialPort.waitForReadyRead(10);
    }
    return m_serialPort.read(byte,1);
}

int Balanca::writeByte(char byte)
{
    int result = m_serialPort.write(&byte,1);
    m_serialPort.flush();
    return result;
}

int Balanca::writeData(char *buf, int dataLen) {
    int totalSent = 0;
    unsigned long long initTimeInMillis = currentTimeInMillis();

    while(totalSent<dataLen) {
        unsigned long long ellapsedTimeInMillis = currentTimeInMillis() - initTimeInMillis;

        if( ellapsedTimeInMillis >= m_timeoutInMillis ) break;

        int sent = m_serialPort.write(buf+totalSent,dataLen-totalSent);
        m_serialPort.flush();
        if(sent==-1) {
            break;
        }

        totalSent += sent;
    }

    return totalSent;
}

unsigned long long Balanca::currentTimeInMillis() {
    struct timeb time;

    ftime(&time);

    return time.time*1000 + time.millitm;
}
